import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import threading
import time
import sys
import socket
import pickle
from matplotlib.ticker import MultipleLocator
from matplotlib.ticker import FormatStrFormatter
from queue import Queue
from queue import Empty as QueueEmptyException

ui_queue = Queue(20)


def set_ax(ax):
    # 将x主刻度标签设置为20的倍数(也即以 20为主刻度单位其余可类推)
    xmajorLocator = MultipleLocator(1);
    # 设置x轴标签文本的格式
    xmajorFormatter = FormatStrFormatter('%0.2f')
    # 将x轴次刻度标签设置为5的倍数
    xminorLocator = MultipleLocator(0.5)
    # 设定y 轴的主刻度间隔及相应的刻度间隔显示格式
    # 将y轴主刻度标签设置为1.0的倍数
    ymajorLocator = MultipleLocator(1)
    # 设置y轴标签文本的格式
    ymajorFormatter = FormatStrFormatter('%0.2f')
    # 将此y轴次刻度标签设置为0.2的倍数
    yminorLocator = MultipleLocator(0.5)
    # 设置主刻度标签的位置,标签文本的格式
    ax.xaxis.set_major_locator(xmajorLocator)
    ax.xaxis.set_major_formatter(xmajorFormatter)
    ax.yaxis.set_major_locator(ymajorLocator)
    ax.yaxis.set_major_formatter(ymajorFormatter)

    # 显示次刻度标签的位置,没有标签文本
    ax.xaxis.set_minor_locator(xminorLocator)
    ax.yaxis.set_minor_locator(yminorLocator)
    ax.xaxis.grid(True, linestyle='-.', which='major')  # x坐标轴的网格使用主刻度
    # ax.yaxis.grid(True, which='minor')  # y坐标轴的网格使用次刻度
    ax.yaxis.grid(True, linestyle='-.', which='major')  # x坐标轴的网格使用主刻度


route_position = ((0.0, 0.0), (10.0, 10.0), (5.0, 10.0))
fig, ax = plt.subplots()
set_ax(ax)
xdata, ydata = [0], [5]
ln, = ax.plot([], [], 'rx', animated=False)
circ1 = plt.Circle(route_position[0], 5, color='b', alpha=0.2)  # 圆心，半径，颜色，α
ax.add_patch(circ1)
circ2 = plt.Circle(route_position[1], 5, color='r', alpha=0.2)  # 圆心，半径，颜色，α
ax.add_patch(circ2)
circ3 = plt.Circle(route_position[2], 5, color='g', alpha=0.2)  # 圆心，半径，颜色，α
ax.add_patch(circ3)
ax.plot([x[0] for x in route_position], [x[1] for x in route_position], 'ko', animated=False, ms=10)


def init():
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    return ln,


def update(frame):
    ln.set_data(xdata, ydata)
    return ln,


# ani = FuncAnimation(fig, update, init_func=init, blit=True)

is_thread_run = True
def loop():
    while is_thread_run:
        while is_thread_run:
            try:
                HOST = '127.0.0.1'
                PORT = 8888
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((HOST, PORT))
                break
            except BaseException as e:
                runnable = Runnable(lambda: ax.set_title('no link'))
                ui_queue.put(runnable)
            time.sleep(1)
        runnable = Runnable(lambda: ax.set_title('linked'))
        ui_queue.put(runnable)
        while is_thread_run:
            try:
                input_str = s.recv(1024)
                input_str = pickle.loads(input_str)
                #print(input_str)
                # print(type(input_str))
                if input_str[0] is not None and len(input_str[0]) >= 2:
                    xdata.append(input_str[0][0])
                    ydata.append(input_str[0][1])
                    #print(xdata[0], ydata[0])
                    if len(input_str[0]) == 3:
                        runnable = Runnable(lambda :circ2.set_radius(input_str[0][2] + 1))
                        ui_queue.put(runnable)
            except Exception:
                break
        s.close()


class Runnable():
    def __init__(self, run):
        self.run = run


def UILoop():
    while (is_thread_run):
        init()
        update(None)
        try:
            runnable = ui_queue.get(block=False, timeout=0.5)
            runnable.run()
        except QueueEmptyException:
            pass
        plt.pause(0.001)


if __name__ == '__main__':
    t = threading.Thread(target=loop, name='UIThread')
    t.start()
    UILoop()
    # plt.show()
    print('over')
    is_thread_run = False
    sys.exit(0)
